import re


def template(fun_name: str, params: list, description: str, url: str, headers,
             fun_method: str):
    '''
    :param:params: [{name:key_name, description:str|none, required:bool, type:str, value:any, in:str}},..]
    :param:header: {key:value}
    :return:None
    '''
    if '{' in url:
        url = 'f"' + url + '"'
    else:
        url = '"' + url + '"'
    if re.match(r'[0-9]', fun_name):
        fun_name = 'v' + fun_name

    payload = extract_body(params)
    if 'MultipartEncoder' in payload:
        fromdata = '\n    from requests_toolbelt import MultipartEncoder'
        headers = "{'Content-Type': payload.content_type}"
    else:
        fromdata = ''
    if description:
        description = '\n    ' + description
    else:
        description = ''

    template = f'''def {fun_name.replace('.','_')}(session{extract_param(params)}):
    \'\'\'{description}
    {extract_desc(params)}:return:list/dict
    \'\'\'{fromdata}
    url = settings.BASE_API_URL + {url}
    payload = {extract_body(params)}
    headers = {headers}
    response = session.{fun_method}(url, headers = headers, data = payload, params = {{{extract_url_param(params)}}})
    assert response.status_code==200
    return json.loads(response.text)

'''
    return template


def case_template(file_name, fun_name: str, params: list, description: str,
                  output_dir):
    '''
    :param:params: [{name:key_name, description:str|none, required:bool, type:str, value:any, in:str}},..]
    :param:header: {key:value}
    :return:None
    '''
    if re.match(r'[0-9]', fun_name):
        fun_name = 'v' + fun_name
    file_name = file_name.lower()
    template = f'''@pytest.mark.parametrize('{extract_param(params).replace('=None','').replace(':list','')[2:]}',[])
def test_{fun_name.replace('.','_')}(session{extract_param(params).replace('=None','')}):
    \'\'\'
    {description}
    {extract_desc(params)}:return:list/dict
    \'\'\'
    from {output_dir.split('/')[-2] }.{file_name} import {fun_name.replace('.','_')}
    tmp = {fun_name.replace('.','_')}(session{extract_param(params).replace('=None','').replace(':list','')})

'''
    return template


def extract_param(params):
    '''
    :param:params: [{name:key_name, description:str|none, required:bool, type:str, value:any, in:str}},..]
    :return:str
    '''
    param_first = ''
    param_last = ''
    chongfu = []

    for x in params:
        chongfu.append(x['name'])
    for n in chongfu:
        if chongfu.count(n) > 1:
            params[chongfu.index(n)]['name'] = params[chongfu.index(
                n)]['name'] + '_' + params[chongfu.index(n)]['in']
            chongfu.remove(n)
    for i in params:
        if i['in'] == 'path':
            if i['required']:
                param_first += f", {i['name']}"
            else:
                param_last += f", {i['name']}=None"
        elif i['in'] == 'query':
            if i['required']:
                param_first += f", {i['name']}"
            else:
                param_last += f", {i['name']}=None"
        elif i['in'] == 'body':
            if i['schema']['type'] == 'object':
                for n in i['schema']['properties'].keys():
                    param_last += f", {n}=None"
            elif i['schema']['type'] == 'array':
                param_last += f", {i['name']}:list"
        elif i['in'] == 'formData':
            if i['required']:
                param_first += f", {i['name']}"
            else:
                param_last += f", {i['name']}=None"

    return param_first + param_last


def extract_url_param(params):
    chongfu = []
    url_param = ''

    for x in params:
        chongfu.append(x['name'])
    for n in chongfu:
        if chongfu.count(n) > 1:
            params[chongfu.index(n)]['name'] = params[chongfu.index(
                n)]['name'] + '_' + params[chongfu.index(n)]['in']
            chongfu.remove(n)
    for i in params:
        if i['in'] == 'query':
            url_param += f"'{i['name']}':{i['name']}, "
    return url_param


def extract_desc(params):
    '''
    :param:params: [{name:key_name, description:str|none, required:bool, type:str, value:any, in:str}},..]
    :return:None
    '''
    param_desc = ''
    for i in params:
        if i['in'] == 'path' or i['in'] == 'query':
            param_desc += f':param:{i["name"]}:{i["type"]}:{i["description"].replace(" ","")}\n    '
        elif i['in'] == 'body':
            if i['schema']['type'] == 'object':
                for (k, v) in i['schema']['properties'].items():
                    if 'description' in v:
                        param_desc += f':param:{k}:{v["type"]}:{v["description"].replace(" ","")}\n    '
                    else:
                        param_desc += f':param:{k}:{v["type"]}\n    '
            elif i['schema']['type'] == 'array':
                param_desc += f":param:{i['name']}:list\n    "
    return param_desc


def extract_body(params):
    '''
    :param:params: [{name:key_name, description:str|none, required:bool, type:str, value:any, in:str}},..]
    :return:None
    '''

    body_object = ''
    formdata_params = ''
    body_array = ''
    for i in params:
        if i['in'] == 'body':
            if i['schema']['type'] == 'object':
                for n in i['schema']['properties'].keys():
                    body_object += f'"{n}":{n}, '
            elif i['schema']['type'] == 'array':
                body_array += f"{i['name']}"
        elif i['in'] == 'formData':
            formdata_params += f'"{i["name"]}": {i["name"]}, '
    if body_object:
        body_object = "json.dumps({" + body_object[:-2] + "})"
        return body_object
    if body_array:
        body_array = 'json.dumps(' + body_array + ')'
        return body_array
    if formdata_params:
        formdata_params = "MultipartEncoder(fields={" + formdata_params + "})"
        return formdata_params
    else:
        return '{}'

